package com.woniuxy.shiro_config;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.woniuxy.entity.RbacManager;
import com.woniuxy.entity.RbacRole;
import com.woniuxy.service.RbacManagerService;
import com.woniuxy.service.RbacPermService;
import com.woniuxy.service.RbacRoleService;
import com.woniuxy.utils.JWTUtils;
import com.woniuxy.utils.MyJsonWebToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Set;

//jwt自定义域，专门用来处理MyJsonWebToken对象
@Component
public class MyJWTRealm extends AuthorizingRealm {

    private final String REALMNAME="MyJWTRealm";
    @Autowired
    RbacManagerService rbacManagerService;
    @Autowired
    RbacRoleService rbacRoleService;
    @Autowired
    RbacPermService rbacPermService;
    @Autowired
    RedisTemplate redisTemplate;
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof MyJsonWebToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = principals.getPrimaryPrincipal()+"";
        //访问数据库获取对应的角色set集合
        Set<String> rbacRoles = rbacRoleService.findOneByUserName(username);
        //存放的是角色信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(rbacRoles);
        //查询当前登录用户的权限信息
        Set<String> rbacPerms = rbacPermService.findPermBySetRoles(username);
        simpleAuthorizationInfo.setStringPermissions(rbacPerms);
        return simpleAuthorizationInfo;
    }
    //认证方法的开发！
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = authenticationToken.getCredentials()+"";
        //第二个版本 shiro+redis进行权限认证优化
        RbacManager rbacManager = (RbacManager) redisTemplate.opsForValue().get(token);
        if (rbacManager == null) {
            throw new AuthenticationException("缓存过期。");
        }
        try {
            //进行过期校验和防篡改校验, 只有一个结果，如果不是true则直接抛出异常,jwt的校验异常
            JWTUtils.verify(token, rbacManager.getAccount(),rbacManager.getPassword());
        }catch (JWTVerificationException e){
            //转换封装一下，变成认证异常
            throw new AuthenticationException(e.getMessage());
        }
        return new SimpleAuthenticationInfo(rbacManager.getAccount(),token,REALMNAME);
    }
}